/**
 * 基础Singleton类
 * 这是一个空的基础类，将通过SingletonExp函数包装为单例模式
 */
class Singleton {
  constructor() {}
}

// 不推荐使用，因为它会创建一个全局实例，而不是在需要时才创建
export const singletonIns = new Singleton();

/**
 * 单例模式包装器（高阶函数）
 * 接收一个类作为参数，返回一个经过Proxy包装的单例版本
 *
 * @param {Function} className - 要包装的目标类
 * @returns {Proxy} - 包装后的单例类代理
 */
const SingletonExp = (className) => {
  // 用于存储唯一实例的变量
  // 闭包变量，确保实例在多次调用时保持唯一
  let ins;

  // Web Worker 环境下的并发问题解决方案
  // 标志位，用于判断是否正在初始化实例
  let initializing = false;
  // 存储等待实例创建完成的回调函数队列
  let instanceQueue = [];

  // 使用Proxy包装目标类，拦截构造函数调用
  return new Proxy(className, {
    /**
     * 拦截构造函数调用的处理函数
     * 确保无论调用多少次new，都只返回同一个实例
     * @param {Function} target - 被代理的目标类（即传入的className）
     * @param {Array} args - 构造函数的参数列表
     * @returns {Object} - 唯一的类实例
     */
    construct(target, args) {
      // 检查实例是否已存在
      if (ins) {
        return ins;
      }
      // 正在初始化，加入队列等待
      if (initializing) {
        // 返回Promise供Worker间通信使用
        return new Promise((resolve) => {
          instanceQueue.push(resolve);
        });
      }

      try {
        initializing = true;
        ins = Reflect.construct(target, args);
        // 通知等待的调用者
        instanceQueue.forEach((resolve) => resolve(ins));
        instanceQueue = [];
        return ins;
      } catch (error) {
        // 初始化过程中出错，重置标志位
        initializing = false;
      }
      // if (!ins) {
      //   // 如果实例不存在，使用Reflect.construct创建新实例
      //   // Reflect.construct相当于new target(...args)，但更适合在Proxy中使用
      //   ins = Reflect.construct(target, args);
      // }
      // // 返回唯一实例（无论是新创建的还是已存在的）
      // return ins;
    },
  });
};

/**
 * 导出经过单例包装的Singleton类(是一个代理包装的类)
 * 当外部通过import导入并使用new操作符时，始终获取同一个实例
 */
export default SingletonExp(Singleton);
